package com.gmall.product.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gmall.common.constants.MqConst;
import com.gmall.common.result.Result;
import com.gmall.model.product.SkuAttrValue;
import com.gmall.model.product.SkuImage;
import com.gmall.model.product.SkuInfo;
import com.gmall.product.mapper.SkuAttrValueMapper;
import com.gmall.product.mapper.SkuImageMapper;
import com.gmall.product.mapper.SkuInfoMapper;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class SkuService {

    @Autowired
    SkuInfoMapper skuInfoMapper;

    @Autowired
    SkuImageMapper skuImageMapper;

    @Autowired
    SkuAttrValueMapper skuAttrValueMapper;

    @Autowired
    RabbitTemplate rabbitTemplate;
    @Autowired
    RedisTemplate redisTemplate;
    private final String SKU_INFO_KEY_TEMPLATE = "Sku:";
    @Transactional
    public Result<String> saveSkuInfo(SkuInfo skuInfo) {

        skuInfo.setIsSale(0);//下架
        skuInfoMapper.insert(skuInfo);

        Long skuId = skuInfo.getId();
        List<SkuImage> skuImageList = skuInfo.getSkuImageList();
        skuImageList.forEach(skuImage -> {
            skuImage.setSkuId(skuId);
            skuImageMapper.insert(skuImage);
            if(skuImage.getIsDefault()=="1"){
                skuInfo.setSkuDefaultImg(skuImage.getImgUrl());
            }
        });


        List<SkuAttrValue> skuAttrValueList = skuInfo.getSkuAttrValueList();

        skuAttrValueList.forEach(skuAttrValue -> {
            skuAttrValue.setSkuId(skuId);
            skuAttrValueMapper.insert(skuAttrValue);
        });
        RBloomFilter<Long> skuListBloomFilter = redisson.getBloomFilter("skuListBloomFilter");
        skuListBloomFilter.add(skuInfo.getId());//添加到布隆过滤器
        return  Result.ok();
    }

    public Result<IPage<SkuInfo>> getSkuInfoPage(Integer pageNo, Integer pageSize, Map searchMap) {


        IPage<SkuInfo> skuInfoIPage = new Page<>(pageNo, pageSize);


        QueryWrapper<SkuInfo> queryWrapper = new QueryWrapper<>();
        if(searchMap!=null){
            String category3Id = (String)searchMap.get("category3Id");
            if(!StringUtils.isEmpty(category3Id)){
                queryWrapper.lambda().eq(SkuInfo::getCategory3Id,category3Id);
            }
            String tmId = (String)searchMap.get("tmId");
            if(!StringUtils.isEmpty(tmId)){
                queryWrapper.lambda().eq(SkuInfo::getTmId,tmId);
            }

            String skuName = (String)searchMap.get("skuName");
            if(!StringUtils.isEmpty(tmId)){
                queryWrapper.lambda().like(SkuInfo::getSkuName,skuName);
            }
        }

        IPage<SkuInfo> skuInfoIPage1 = skuInfoMapper.selectPage(skuInfoIPage, queryWrapper);
        return Result.ok(skuInfoIPage1);

    }

    /**
     * 上架
     * @param skuId
     * @return
     */
    public Result<String> onSale(Long skuId) {

        //selct * from sku_info where id = #{skuId}
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        skuInfo.setIsSale(1);

        //update sku_info set is_sale = 1 where id = #{skuId}
        skuInfoMapper.updateById(skuInfo);

        rabbitTemplate.convertAndSend(MqConst.EXCHANGE_DIRECT_GOODS,
                MqConst.ROUTING_GOODS_UPPER,skuId+"");
        return Result.ok("上架成功");

    }


    /**
     * 下架
     * @param skuId
     * @return
     */
    public Result<String> cancelSale(Long skuId) {

        //update sku_info set is_sale = 0 where id = #{skuId} //可以更新多条记录
        SkuInfo skuInfo = new SkuInfo();
        skuInfo.setIsSale(0);
        UpdateWrapper<SkuInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(SkuInfo::getId,skuId);
        skuInfoMapper.update(skuInfo,updateWrapper);
        rabbitTemplate.convertAndSend(MqConst.EXCHANGE_DIRECT_GOODS,
                MqConst.ROUTING_GOODS_LOWER,skuId+"");
        return Result.ok("下架成功");
    }

    /**
     * 查询出在lastSynDateTime 时间之后修改的sku信息
     * @param lastSynDateTime
     * @return
     */
    public List<SkuInfo> getSkuInfoListAfterDateTime(Date lastSynDateTime) {

        QueryWrapper<SkuInfo> queryWrapper = new QueryWrapper<>();
        if(lastSynDateTime!= null){
            queryWrapper.lambda().gt(SkuInfo::getUpdateTime,lastSynDateTime);
            queryWrapper.lambda().eq(SkuInfo::getIsSale,1);
            //select * from sku_info where update_time > #{lastSynDateTime}
        }
        List<SkuInfo> skuInfos = skuInfoMapper.selectList(queryWrapper);//select * from sku_info
        return skuInfos;
    }

    public Result<String> updateSkuInfo(SkuInfo skuInfo) {
        if(skuInfo.getId()!=null){
            redisTemplate.delete(SKU_INFO_KEY_TEMPLATE + skuInfo.getId());
            skuInfoMapper.updateById(skuInfo);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            redisTemplate.delete(SKU_INFO_KEY_TEMPLATE + skuInfo.getId());
        }
        return Result.ok();
    }

    @PostConstruct
    public void initBloomFilter(){
        System.out.println("初始化布隆过滤器");
        RBloomFilter<Long> skuListBloomFilter = redisson.getBloomFilter("skuListBloomFilter");

        List<SkuInfo> skuInfoList = skuInfoMapper.selectList(null);
        skuListBloomFilter.tryInit(skuInfoList.size()*2,0.03);
        for (SkuInfo skuInfo : skuInfoList) {
            skuListBloomFilter.add(skuInfo.getId());
        }
    }

    @Autowired
    RedissonClient redisson;
    public Result<SkuInfo> getSkuInfoById(Long skuId) {
        RBloomFilter<Long> skuListBloomFilter = redisson.getBloomFilter("skuListBloomFilter");
        //没有：确定的 布隆过滤器解决了缓存穿透的问题
        if(!skuListBloomFilter.contains(skuId)){
            return Result.fail();
        }
        RLock lock = redisson.getLock("sku:lock:" + skuId);//解决了缓存击穿的问题
        lock.lock();
        try {
            SkuInfo skuInfo_fromRedis = (SkuInfo) redisTemplate.opsForValue().get(SKU_INFO_KEY_TEMPLATE + skuId);
            if (skuInfo_fromRedis == null) {
                System.out.println("Redis 不存在 SKU " + skuId);
                SkuInfo skuInfo_fromDB = skuInfoMapper.selectById(skuId);//费时间
                System.out.println("从数据库查询 " + skuId);
                redisTemplate.opsForValue().set(SKU_INFO_KEY_TEMPLATE + skuId, skuInfo_fromDB);
                System.out.println("装入Redis " + skuId);
                return Result.ok(skuInfo_fromDB);
            }
            System.out.println("Redis 中存在，直接返回" + skuId);
            return Result.ok(skuInfo_fromRedis);
        }finally {
            lock.unlock();
        }
    }
}
